package com.lmind.core.gps;

import java.net.InetSocketAddress;
import java.util.concurrent.ScheduledThreadPoolExecutor;
import java.util.concurrent.atomic.AtomicInteger;

import org.junit.AfterClass;
import org.junit.Assert;
import org.junit.BeforeClass;
import org.junit.Test;

import com.lmind.core.async.ResultHandler;
import com.lmind.core.gis.Location;
import com.lmind.core.gps.alone.VirtualSmartphone;
import com.lmind.core.gps.gateway.GatewayMessageContext;
import com.lmind.core.gps.gateway.SmartphoneGateway;
import com.lmind.core.gps.terminal.message.AbstractMessage;
import com.lmind.core.gps.terminal.message.LocateMessage;
import com.lmind.core.gps.terminal.message.ReplyMessage;
import com.lmind.core.message.AsyncMessageProcessor;
import com.lmind.core.message.JavaMessageCodec;
import com.lmind.core.message.MessageCodec;

public class SmartphoneGatewayTestCase {
	
	private static SmartphoneGateway gateway = new SmartphoneGateway();
	
	private static ScheduledThreadPoolExecutor executor;
	
	private static String deviceSerial = "13112345678";
	
	private static MessageCodec codec = SmartphoneGateway.createCodec();
	
	@BeforeClass
	public static void beforeClass() throws Exception {
		
		executor = new ScheduledThreadPoolExecutor(1);
		gateway.setMessageCodec(codec);
		gateway.setScheduledExecutor(executor);
		gateway.setProcessor(new AsyncMessageProcessor<GatewayMessageContext, AbstractMessage>() {
			@Override
			public void process(GatewayMessageContext context,
					AbstractMessage message, ResultHandler<AbstractMessage> handler) {
				
			}
		});
		gateway.bind(new InetSocketAddress(15443));
	}
	
	@AfterClass
	public static void afterClass() throws Exception {
		gateway.close();
		executor.shutdown();
	}

	//@Test
	public void test() throws Exception {
		
		VirtualSmartphone terminal = new VirtualSmartphone();
		terminal.setMessageCodec(codec);
		terminal.setExecutorService(executor);
		terminal.setDeviceSerial("13112345678");
		terminal.setLocation(new Location(40, 110));
		terminal.setInterval(5000);
		terminal.connect(new InetSocketAddress("127.0.0.1", 15443));
		
		Thread.sleep(20 * 1000);
		terminal.close();
	}

	@Test
	public void test2() throws Exception {
		
		VirtualSmartphone terminal = new VirtualSmartphone();
		
		try {
			terminal.setExecutorService(executor);
			terminal.setMessageCodec(codec);
			terminal.setDeviceSerial(deviceSerial);
			terminal.setLocation(new Location(40, 110));
			terminal.setInterval(5000);
			terminal.connect(new InetSocketAddress("127.0.0.1", 15443));
			Thread.sleep(1 * 1000);
			class Handler implements ResultHandler<ReplyMessage> {
				private AtomicInteger successCount = new AtomicInteger(0);

				public int getSuccessCount() {
					return successCount.get();
				}

				public void result(ReplyMessage result) {
					if (result.isSuccess())
						successCount.incrementAndGet();
				}

				public void exception(Throwable e) {
					Assert.fail(e.getMessage());
					e.printStackTrace();
				}
			}
			Handler handler = new Handler();
			int loop = 100;
			for (int i = 0; i < loop; i++) {
				gateway.send(deviceSerial, new LocateMessage(), handler);
			}
			for (int i = 0; i < 100; i++) {
				if (handler.getSuccessCount() == loop)
					break;
				Thread.sleep(100);
			}
			Assert.assertEquals(loop, handler.getSuccessCount());
		} finally {
			terminal.close();
		}
	}
}
